/*
    Copyright 2009 Spencer B. Koehler, Ph.D.

    This file is part of the Brillig Toolkit.

    The Brillig Toolkit is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    The Brillig Toolkit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with The Brillig Toolkit.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.brillig.xml;

import org.brillig.util.tree.Tree;
import org.brillig.util.tree.TreeAnalyzer;
import org.brillig.util.tree.Tree2Dot;

import java.io.File;
import java.io.IOException;
import java.io.Writer;

/**
 * Utility class for converting an xml file to dot format.
 * <p>
 * Dot format is a text file representing a graph that can be turned
 * into an image using AT&amp;T's GraphViz project.
 * <p>
 * For example, the following command will turn a dot (text) file
 * generated by this utility into a png image.
 * <p>
 * dot -Tpng x.dot -o x.png
 *
 * @author Spence Koehler
 */
public class Xml2Dot {

  public static final class XmlLabelMaker implements Tree2Dot.LabelMaker<XmlLite.Data> {
    public String makeLabel(Tree<XmlLite.Data> node, TreeAnalyzer<XmlLite.Data> treeAnalyzer) {
      final StringBuilder result = new StringBuilder();

      final XmlLite.Data data = node.getData();
      final XmlLite.Tag tag = data.asTag();
      final XmlLite.Text text = data.asText();
      final XmlLite.Comment comment = data.asComment();

      if (tag != null) {
        result.append(tag.name);

        if (treeAnalyzer != null) {
          final TreeAnalyzer<XmlLite.Data>.NodeInfo nodeInfo = treeAnalyzer.getNodeInfo(node);
          if (nodeInfo.hasFlag("recordSection")) result.append("*RS");
          if (nodeInfo.hasFlag("record")) result.append("*R");
        }
      }
      else if (text != null) {
        final int len = text.text.length();
        result.append("text");

        if (treeAnalyzer != null) {
          final TreeAnalyzer<XmlLite.Data>.NodeInfo nodeInfo = treeAnalyzer.getNodeInfo(node);
          if (nodeInfo.hasFlag("data")) result.append("*D");
          if (nodeInfo.hasFlag("consecutive")) result.append("+");
        }

        result.append("=\\\"");

        int limit = (len <= 8) ? len : 5;
        for (int i = 0; i < len && i < limit; ++i) {
          final char c = text.text.charAt(i);
          if (c == '"') {
            ++limit;
          }
          else {
            result.append(c);
          }
        }
        if (limit != len) result.append("...");
        result.append("\\\"");
      }
      else if (comment != null) {
        result.append("<comment>");
      }

      return result.toString();
    }
  }

  public static final void main(String[] args) throws IOException {
    if (args.length != 2) {
      System.out.println("Usage: Xml2Dot xmlInputFile outputFile");
    }
    else {
      final Tree<XmlLite.Data> xmlTree = XmlFactory.readXmlTree(new File(args[0]), true, true, false);

      final Writer writer = org.brillig.io.FileUtil.getWriter(args[1]);
      final Tree2Dot<XmlLite.Data> tree2dot = new Tree2Dot<XmlLite.Data>(xmlTree, null, new XmlLabelMaker());
      tree2dot.writeDot(writer);
      writer.close();
    }
  }
}
